/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.meteoCal.entity;

import it.polimi.meteoCal.control.PasswordEncrypter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.swing.ImageIcon;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

/**
 *
 * @author Utente
 */
@Entity(name = "USERS")
@NamedQueries({
    @NamedQuery(name = Users.findByUsername,
            query = "SELECT u.username FROM USERS u WHERE u.username = :username"),
    @NamedQuery(name = Users.findByEmail,
            query = "SELECT u.email FROM USERS u WHERE u.email = :email"),
    @NamedQuery(name = Users.findAll,
            query = "SELECT u FROM USERS u WHERE NOT(u.username = :username)")
})
public class Users implements Serializable {

    private static final long serialVersionUID = 1L;
    public static final String findByUsername = "Users.findByUsername";
    public static final String findByEmail = "Users.findByEmail";
    public static final String findAll = "Users.findAll";
    //Entity attributes
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @NotNull(message = "May not be empty")
    private String username;

    @NotNull(message = "May not be empty")
    private String name;

    @NotNull(message = "May not be empty")
    private String surname;

    @Pattern(regexp = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?",
            message = "invalid email")
    @NotNull(message = "May not be empty")
    private String email;

    @NotNull(message = "May not be empty")
    @Temporal(TemporalType.DATE)
    private Date dateOfBirth;

    @NotNull(message = "May not be empty")
    private String password;

    @NotNull
    @OneToOne(optional = false, cascade = CascadeType.ALL)
    private Calendar calendar;

    private ImageIcon avatar;

    private String description;

    @OneToMany(cascade = CascadeType.ALL, targetEntity = Request.class, mappedBy = "user", orphanRemoval = true)
    private List<Request> requestsReceived;

    @OneToMany(cascade = CascadeType.ALL, targetEntity = Updates.class, mappedBy = "user", orphanRemoval = true)
    private List<Updates> updatesReceived;

    @OneToMany(cascade = CascadeType.ALL, targetEntity = BadWeatherNotification.class, mappedBy = "user", orphanRemoval = true)
    private List<BadWeatherNotification> badWeatherNotificationsReceived;

    @OneToMany(cascade = CascadeType.ALL, targetEntity = Suggestion.class, mappedBy = "user", orphanRemoval = true)
    private List<Suggestion> suggestionsReceived;

    @NotNull
    private String type;

    public Users() {
        requestsReceived = new ArrayList<>();
        updatesReceived = new ArrayList<>();
        badWeatherNotificationsReceived = new ArrayList<>();
        suggestionsReceived = new ArrayList<>();
    }

    /**
     *
     * @return the user's username
     */
    public String getUsername() {
        return username;
    }

    /**
     *
     * @param username the user's username
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     *
     * @return the user's name
     */
    public String getName() {
        return name;
    }

    /**
     *
     * @param name the user's name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     * @return the user's surname
     */
    public String getSurname() {
        return surname;
    }

    /**
     *
     * @param surname the user's surname
     */
    public void setSurname(String surname) {
        this.surname = surname;
    }

    /**
     *
     * @return the user's email
     */
    public String getEmail() {
        return email;
    }

    /**
     *
     * @param email the user's email
     */
    public void setEmail(String email) {
        this.email = email;
    }

    /**
     *
     * @return the user's birthdate
     */
    public Date getDateOfBirth() {
        return dateOfBirth;
    }

    /**
     *
     * @param dateOfBirth the user's birthdate
     */
    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    /**
     *
     * @return the user's encrypted password
     */
    public String getPassword() {
        return password;
    }

    /**
     * This method encrypts the password before setting it
     *
     * @param password the user's password
     */
    public void setPassword(String password) {
        this.password = PasswordEncrypter.encryptPassword(password);
    }

    /**
     *
     * @return the user's calendar
     */
    public Calendar getCalendar() {
        return calendar;
    }

    /**
     *
     * @param calendar the user's calendar
     */
    public void setCalendar(Calendar calendar) {
        this.calendar = calendar;
    }

    /**
     *
     * @return the user's avatar
     */
    public ImageIcon getAvatar() {
        return avatar;
    }

    /**
     *
     * @param avatar the user's avatar
     */
    public void setAvatar(ImageIcon avatar) {
        this.avatar = avatar;
    }

    /**
     *
     * @return the user's description
     */
    public String getDescription() {
        return description;
    }

    /**
     *
     * @param description the user's description
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     *
     * @return the user's type
     */
    public String getType() {
        return type;
    }

    /**
     *
     * @param type the user's type
     */
    public void setType(String type) {
        this.type = type;
    }

    public List<Request> getRequestsReceived() {
        if (requestsReceived == null) {
            requestsReceived = new ArrayList<>();
        }
        return requestsReceived;
    }

    public void setRequestsReceived(List<Request> requestsReceived) {
        this.requestsReceived = requestsReceived;
    }

    public void addRequest(Request request) {
        requestsReceived.add(request);
    }

    public Request getRequest(Event event) {
        for (Request r : requestsReceived) {
            if (r.getEvent().equals(event)) {
                return r;
            }
        }
        return null;
    }

    public void removeRequest(Request request) {
        requestsReceived.remove(request);
    }

    /**
     *
     * @return a list with all updates received by the user
     */
    public List<Updates> getUpdatesReceived() {
        if (updatesReceived == null) {
            updatesReceived = new ArrayList<>();
        }
        return updatesReceived;
    }

    /**
     *
     * @param updatesReceived a list with all updates received by the user
     */
    public void setUpdatesReceived(List<Updates> updatesReceived) {
        this.updatesReceived = updatesReceived;
    }

    public void addUpdate(Updates update) {
        this.updatesReceived.add(update);
    }

    public Updates getUpdate(Event event) {
        for (Updates up : updatesReceived) {
            if (up.getEvent().equals(event)) {
                return up;
            }
        }
        return null;
    }

    public void removeUpdate(Updates update) {
        updatesReceived.remove(update);
    }

    /**
     *
     * @return a list with all bad weather notifications received by the user
     */
    public List<BadWeatherNotification> getBadWeatherNotificationsReceived() {
        if (badWeatherNotificationsReceived == null) {
            badWeatherNotificationsReceived = new ArrayList<>();
        }
        return badWeatherNotificationsReceived;
    }

    /**
     *
     * @param badWeatherNotificationsReceived a list with all bad weather
     * notifications received by the user
     */
    public void setBadWeatherNotificationsReceived(List<BadWeatherNotification> badWeatherNotificationsReceived) {
        this.badWeatherNotificationsReceived = badWeatherNotificationsReceived;
    }

    public void addBadWeatherNotification(BadWeatherNotification badWeatherNotification) {
        this.badWeatherNotificationsReceived.add(badWeatherNotification);
    }

    public BadWeatherNotification getBadWeatherNotification(Event event) {
        for (BadWeatherNotification bwn : badWeatherNotificationsReceived) {
            if (bwn.getEvent().equals(event)) {
                return bwn;
            }
        }
        return null;
    }

    public void removeBadWeatherNotification(BadWeatherNotification bwn) {
        badWeatherNotificationsReceived.remove(bwn);
    }

    /**
     *
     * @return a list with all updates received by the user
     */
    public List<Suggestion> getSuggestionsReceived() {
        if (suggestionsReceived == null) {
            suggestionsReceived = new ArrayList<>();
        }
        return suggestionsReceived;
    }

    /**
     *
     * @param updatesReceived a list with all updates received by the user
     */
    public void setSuggestionsReceived(List<Suggestion> suggestionsReceived) {
        this.suggestionsReceived = suggestionsReceived;
    }

    public void addSuggestion(Suggestion suggestion) {
        this.suggestionsReceived.add(suggestion);
    }

    public Suggestion getSuggestion(Event event) {
        for (Suggestion s : suggestionsReceived) {
            if (s.getEvent().equals(event)) {
                return s;
            }
        }
        return null;
    }

    public void removeSuggestion(Suggestion suggestion) {
        suggestionsReceived.remove(suggestion);
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (username != null ? username.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Users)) {
            return false;
        }
        Users other = (Users) object;
        if (!this.username.equals(other.username)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return username;
    }

}
